package com.rinlink.jbcodec.transform;


import com.alibaba.fastjson.JSONObject;
import com.rinlink.jbcodec.JSONCodec;
import com.rinlink.jbcodec.ObjectToBytesCreatorMap;
import com.rinlink.jbcodec.context.ObjectToBytesCreatorContext;
import com.rinlink.jbcodec.creator.ObjectToBytesCreator;
import com.rinlink.jbcodec.exception.CreateTransformException;
import com.rinlink.jbcodec.exception.TransformException;

import java.util.List;


public class JSONToBytes implements Transform<byte[]> {

    public JSONObject data;
    private JSONCodec.Scheme scheme;
    private ObjectToBytesCreatorMap creatorMap;

    public JSONToBytes(JSONObject data, JSONCodec.Scheme scheme, ObjectToBytesCreatorMap creatorMap){
        this.scheme = scheme;
        this.data = data;
        this.creatorMap = creatorMap;
    }

    @Override
    public byte[] transform() throws TransformException {
        List<JSONCodec.Field> fieldsSchemes = scheme.getFields();
        int fieldsSize = scheme.getFields().size();
        byte[][] fieldsBytes = new byte[fieldsSize][];
        int resultBytes = 0;
        for (int i = 0; i < fieldsSize; i++){
            JSONCodec.Field field = fieldsSchemes.get(i);
            ObjectToBytesCreator creator = creatorMap.get(field.getType());
            ObjectToBytesCreatorContext ctx = new ObjectToBytesCreatorContext(scheme,data,fieldsBytes);
            Transform<byte[]> transform = null;
            try {
                transform = creator.create(i,ctx);
            }catch (Exception e){
                RuntimeException ex = new CreateTransformException(String.format("Field `%s` create transform failed, %s",field.getName(),e.getMessage()));
                ex.setStackTrace(e.getStackTrace());
                throw ex;
            }
            byte[] fieldBytes = null;
            try {
                fieldBytes = transform.transform();
            }catch (Exception e){
                RuntimeException ex = new CreateTransformException(String.format("Field `%s` transform failed, %s",field.getName(),e.getMessage()));
                ex.setStackTrace(e.getStackTrace());
                throw e;
            }

            fieldsBytes[i] = fieldBytes;
            resultBytes += fieldBytes.length;
        }

        byte[] result = new byte[resultBytes];

        int resultPos = 0;
        for (int i = 0; i < fieldsSize; i++){
            byte[] field = fieldsBytes[i];
            System.arraycopy(field,0,result,resultPos,field.length);
            resultPos += field.length;
        }
        return result;
    }
}
